home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / archvrs / mac / uudecdsr.hqx / uudecode.c next >
Encoding:
C/C++ Source or Header  |  1988-12-09  |  6.8 KB  |  277 lines

  1. /* #ifndef lint
  2. static char sccsid[] = "@(#)uudecode.c  5.3-1 (Berkeley) 9/1/87";
  3. #endif */
  4.  
  5. /* Written by Mark Horton */
  6. /* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */
  7. /* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  8.    compatibility */
  9. /* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a misleading
  10.    error message on the Amiga port, to fix a bug that prevented decoding
  11.    certain files, to work even if trailing spaces have been removed from a
  12.    file, to check the filesize (if present), to add some error checking, to
  13.    loop for multiple decodes from a single file, and to handle common
  14.    BITNET mangling.  Also kludged around a missing string function in Aztec
  15.    C */
  16. /*    Modified by ctj (Chris Jewell, chrisj@cup.portal.com) to catch a
  17.     character which got lost in transmission, for LightSpeed C command line
  18.     support, and to alias index to strchr for LightSpeed and Unix.
  19.     For the Mac, we assume that the output should be written in binary,
  20.     which means that \n is NOT converted to \r. */
  21.  
  22. #define LSC                /* ctj */
  23.  
  24. /*
  25.  * uudecode [input]
  26.  *
  27.  * Decode a file encoded with uuencode.  WIll extract multiple encoded
  28.  * modules from a single file.    Can deal with most mangled files, including
  29.  * BITNET.
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <ctype.h>
  34.  
  35. #ifdef AMIGA
  36. #undef LSC                    /* ctj */
  37. #define AMIGA_LATTICE        /* Set for Amiga Lattice C */
  38. #define MCH_AMIGA
  39. #define MPU68000
  40. #endif
  41.  
  42. #ifdef unix
  43. #undef LSC                    /* ctj */
  44. #define index(sc,c) strchr(sc,c)    /* ctj */
  45. #include <pwd.h>
  46. #include <sys/types.h>
  47. #include <sys/stat.h>
  48. #endif
  49.  
  50. #ifdef LSC
  51. #include <strings.h>
  52. #define index(sc,c) strchr(sc,c)
  53. #endif
  54.  
  55. #define SUMSIZE 64
  56. #define DEC(c)    (((c) - ' ') & 077)    /* single character decode */
  57.  
  58. #ifdef LSC
  59. _main(argc, argv)        /* ctj */
  60. #else
  61. main(argc, argv)
  62. #endif
  63. char **argv;
  64. {
  65. FILE    *in, *out;
  66. int    through_loop=0; /* Dejavu indicator */
  67. int    mode;        /* file's mode (from header) */
  68. long    filesize;    /* theoretical file size (from header) */
  69. char    dest[128];
  70. char    buf[80];
  71.  
  72. #ifdef AMIGA_LATTICE
  73. extern    int Enable_Abort;
  74.     Enable_Abort=1;
  75. #endif
  76.  
  77.     /* A filename can be specified to be uudecoded, or nothing can
  78.     be specified, and the input will come from STDIN */
  79.  
  80.     switch (argc)
  81.     {    case 1:
  82.             in=stdin;
  83.             break;
  84.  
  85.         case 2:
  86.             if ((in = fopen(argv[1], "r")) == NULL)
  87.             {   fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
  88.                 fprintf(stderr, "USAGE: uudecode [infile]\n");
  89.                 exit(10);
  90.             }
  91.             break;
  92.     
  93.         default:
  94.             fprintf(stderr, "USAGE: uudecode [infile]\n");
  95.             exit(11);
  96.             break;
  97.     }
  98.  
  99.     /* Loop through file, searching for headers.  Decode anything with a
  100.        header, complain if there where no headers. */
  101.  
  102.     for (;;)    /* forever */
  103.     {
  104.         /* search file for header line */
  105.         for (;;)
  106.         {    if (fgets(buf, sizeof buf, in) == NULL)
  107.             {    if (!through_loop)
  108.                 {    fprintf(stderr, "ERROR: no `begin' line!\n");
  109.                     exit(12);
  110.                 } else
  111.                 {    exit(0);
  112.                 }
  113.             }
  114.             if (strncmp(buf, "begin ", 6) == 0)
  115.                 break;
  116.         }
  117.         sscanf(buf, "begin %o %s", &mode, dest);
  118.     
  119. #ifdef unix
  120.         /* handle ~user/file format */
  121.         if (dest[0] == '~')
  122.         {    char *sl;
  123.             struct passwd *getpwnam();
  124.             char *index();
  125.             struct passwd *user;
  126.             char dnbuf[100];
  127.         
  128.             sl = index(dest, '/');
  129.             if (sl == NULL)
  130.             {   fprintf(stderr, "Illegal ~user\n");
  131.                 exit(13);
  132.             }
  133.             *sl++ = 0;
  134.             user = getpwnam(dest+1);
  135.             if (user == NULL)
  136.             {   fprintf(stderr, "No such user as %s\n", dest);
  137.                 exit(14);
  138.             }
  139.             strcpy(dnbuf, user->pw_dir);
  140.             strcat(dnbuf, "/");
  141.             strcat(dnbuf, sl);
  142.             strcpy(dest, dnbuf);
  143.         }
  144. #endif
  145.  
  146.         /* create output file */
  147. #ifdef LSC
  148.         if ((out = fopen(dest, "wb")) == NULL)
  149. #else
  150.         if ((out = fopen(dest, "w")) == NULL)
  151. #endif
  152.         {    fprintf(stderr, "ERROR: can't open output file %s\n", dest);
  153.             exit(15);
  154.         }
  155. #ifdef unix
  156.         chmod(dest, mode);
  157. #endif
  158.  
  159.         decode(in, out, dest);
  160.  
  161.         if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3))
  162.         {           /* don't be overly picky about newline ^ */
  163.             fprintf(stderr, "ERROR: no `end' line\n");
  164.             exit(16);
  165.         }
  166.  
  167.         if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3)))
  168.         {    sscanf(buf, "size %ld", &filesize);
  169.             if (ftell(out) != filesize)
  170.             {    fprintf(stderr,
  171.                     "ERROR: file should have been %ld bytes long but was %ld.",
  172.                     filesize, ftell(out));
  173.                 exit(17);
  174.             }
  175.         } /* if (!(fgets ... */
  176.         through_loop = 1;
  177.     }   /* forever */
  178. }   /* main */
  179.  
  180. /*
  181.  * Copy from in to out, decoding as you go.
  182.  * If a return or newline is encountered too early in a line, it is
  183.  * assumed that means that some editor has truncated trailing spaces.
  184.  */
  185. decode(in, out, dest)
  186. FILE *in;
  187. FILE *out;
  188. char *dest;
  189. {
  190. char buf[81];
  191. char *bp;
  192. int nosum=0;
  193. #ifndef unix
  194. extern errno;
  195. #endif
  196. register int j;
  197. register int n;
  198. int checksum, line;
  199.  
  200.     for (line = 1; ; line++)    /* for each input line */
  201.     {    if (fgets(buf, sizeof buf, in) == NULL)
  202.         {   fprintf(stderr, "ERROR: input ended unexpectedly!\n");
  203.             exit(18);
  204.          }
  205.     
  206.         /* Pad end of lines in case some editor truncated trailing spaces */
  207.     
  208.         for (n=0;n<79;n++)  /* search for first \r, \n or \000 */
  209.         {   if (buf[n]=='\176')     /* If BITNET made a twiddle, */
  210.                 buf[n]='\136';     /* we make a caret           */
  211.             if (buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000')
  212.                 break;
  213.         }
  214.         for (;n<79;n++)     /* when found, fill rest of line with space */
  215.             buf[n]=' ';
  216.         
  217.         buf[79]=0;        /* terminate new string */
  218.     
  219.         checksum = 0;
  220.         n = DEC(buf[0]);
  221.         if (n <= 0)
  222.             break;    /* 0 bytes on a line??    Must be the last line */
  223.     
  224.         bp = &buf[1];
  225.     
  226.         /* FOUR input characters go into each THREE output charcters */
  227.     
  228.         while (n >= 4)
  229.         {   j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; putc(j, out); checksum += j;
  230.             j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; putc(j, out); checksum += j;
  231.             j = DEC(bp[2]) << 6 | DEC(bp[3]);       putc(j, out); checksum += j;
  232.             checksum = checksum % SUMSIZE;
  233.             bp += 4;
  234.             n -= 3;
  235.          }
  236.     
  237.         j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  238.         checksum += j;
  239.         if (n >= 1)
  240.             putc(j, out);
  241.  
  242.         j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  243.         checksum += j;
  244.         if (n >= 2)
  245.             putc(j, out);
  246.  
  247.         j = DEC(bp[2]) << 6 | DEC(bp[3]);
  248.         checksum += j;
  249.         if (n >= 3)
  250.             putc(j, out);
  251.  
  252.         checksum = checksum % SUMSIZE;
  253.         bp += 4;
  254.         n -= 3;
  255.     
  256.     #ifndef unix
  257.          /* Error checking under UNIX??? You must be kidding... */
  258.          /* Check if an error occured while writing to that last line */
  259.         if (errno)
  260.         {   fprintf(stderr, "ERROR: error writing to %s\n",dest);
  261.             exit(19);
  262.          }
  263.     #endif
  264.     
  265.         /* The line has been decoded; now check that sum */
  266.     
  267.         nosum |= !isspace(*bp);
  268.         if (nosum)            /* Is there a checksum at all?? */
  269.         {   if (checksum != DEC(*bp))    /* Does that checksum match? */
  270.             {    fprintf(stderr,
  271.                     "ERROR: checksum mismatch decoding %s, line %d.\n",
  272.                     dest, line);
  273.             }
  274.          }    /* nosum */
  275.     }    /* line */
  276. }   /* function */
  277.